﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WSPay.Common.Data;

namespace WSPay.EF
{
    public class UnitOfWork : IUnitOfWork
    {
        private readonly DbContext _context;
        protected bool _disposed;
        private Hashtable _repositories;

        public UnitOfWork(DbContext context)
        {
            _context = context;
        }
        public int Commit()
        {

            return _context.SaveChanges();
        }

        public void Detach<T>(T t) where T : IEntity
        {
            ((IObjectContextAdapter)_context).ObjectContext.Detach(t);
        }

        public IRepository<T> Repository<T>() where T : IEntity
        {
            if (_repositories == null)
                _repositories = new Hashtable();

            var type = typeof(T).Name;

            if (!_repositories.ContainsKey(type))
            {
                var repositoryType = typeof(Repository<>);

                var repositoryInstance =
                    Activator.CreateInstance(repositoryType
                            .MakeGenericType(typeof(T)), _context);

                _repositories.Add(type, repositoryInstance);
            }

            return (IRepository<T>)_repositories[type];
        }



        #region IDisposable
        ~UnitOfWork()
        {
            Dispose(false);
        }

        private void Dispose(bool p)
        {
            if (!_disposed)
            {
                if (_disposed)
                {
                    if (_context != null) _context.Dispose();
                }

                _disposed = true;
            }
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        #endregion


        public int ExecuteSql(string sql, params object[] parameters)
        {
            return _context.Database.ExecuteSqlCommand(sql, parameters);

        }

        public IEnumerable<T> QuerySql<T>(Type elementType, string sql, params object[] parameters)
        {
            return _context.Database.SqlQuery(elementType, sql, parameters).OfType<T>();
        }

    }
}
